#include "musicplayerwidget.h"
#include <QPixmap>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QRegularExpression>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QFile>
#include <QDebug>
#include <QMovie>

MusicPlayerWidget::MusicPlayerWidget(QWidget *parent)
    : QWidget(parent),
      m_player(new QMediaPlayer(this)), // 创建媒体播放器
      m_currentIndex(-1)// 初始化当前歌曲索引为-1(无选中)
{
    // 初始化UI组件
    QFont font;
    font.setPointSize(12); // 设置字体大小为12号
    font.setFamily("楷体"); 
    
    QFont song_font;
    song_font.setBold(true);
    song_font.setPointSize(12); // 设置字体大小为12号
    song_font.setFamily("楷体"); 
    
    m_gifLabel = new QLabel(this);
    
    m_movie = new QMovie(":/img/music1.gif"); // 资源路径或文件路径
    // 将QMovie设置到QLabel
    m_gifLabel->setMovie(m_movie);
   // 启动GIF动画
    m_movie->start();       // 启动QMovie，开始解析帧
    m_movie->jumpToFrame(0); // 跳转到第一帧
    m_movie->setPaused(true); // 保持GIF暂停状态
    m_gifLabel->setFixedSize(50, 50);
    m_gifLabel->setScaledContents(true);
 

    m_songNameLabel = new QLabel(this);
    m_songNameLabel->setFont(song_font);
    m_songNameLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    
    m_artistLabel = new QLabel(this);
    m_artistLabel->setFont(song_font);
    m_artistLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);

    m_lyricLabel = new QLabel(this);
    m_lyricLabel->setFont(font);
    m_lyricLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    m_lyricLabel->setWordWrap(true); // 自动换行

    m_progressSlider = new QSlider(Qt::Horizontal, this);
    m_progressSlider->setStyleSheet(
                "QSlider::groove:horizontal { height: 4px; background: #C0C0C0; border-radius: 4px; }"
                        "QSlider::sub-page:horizontal { background: #4CAF50; border-radius: 4px; }"
                        "QSlider::add-page:horizontal { background: #E0E0E0; border-radius: 4px; }"
                        "QSlider::handle:horizontal { width: 10px; height: 10px; border-image: url(:/img/flower.png); margin: -6px 0;}"
    );

    m_prevBtn = new QLabel(this);
    m_prevBtn->setPixmap(QPixmap(":/img/Previous_song.png"));
    m_prevBtn->setFixedSize(30, 30);
    m_prevBtn->setScaledContents(true);

    m_playBtn = new QLabel(this);
    m_playBtn->setPixmap(QPixmap(":/img/play.png"));
    m_playBtn->setFixedSize(30, 30);
    m_playBtn->setScaledContents(true);

    m_nextBtn = new QLabel(this);
    m_nextBtn->setPixmap(QPixmap(":/img/next_song.png"));
    m_nextBtn->setFixedSize(30, 30);
    m_nextBtn->setScaledContents(true);

    // 布局管理
    QHBoxLayout *btnLayout = new QHBoxLayout;
    btnLayout->addWidget(m_prevBtn);
    btnLayout->addWidget(m_playBtn);
    btnLayout->addWidget(m_nextBtn);


    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(m_gifLabel);
    mainLayout->addWidget(m_songNameLabel);
    mainLayout->addWidget(m_artistLabel);
    mainLayout->addWidget(m_lyricLabel);
    mainLayout->addWidget(m_progressSlider);
    mainLayout->addLayout(btnLayout);

    setLayout(mainLayout);



    // 播放进度变化时，更新进度条和歌词
    connect(m_player, &QMediaPlayer::positionChanged, this, &MusicPlayerWidget::onPositionChanged);
    // 音频时长确定后，设置进度条范围
    connect(m_player, &QMediaPlayer::durationChanged, this, &MusicPlayerWidget::onDurationChanged);
    // 拖拽进度条时，调整播放进度
    connect(m_progressSlider, &QSlider::sliderMoved, this, &MusicPlayerWidget::onProgressDragged);
}


// 从文件读取歌词JSON内容
QString MusicPlayerWidget::readLyricFromFile(const QString& filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning() << "歌词文件打开失败：" << filePath << "，错误：" << file.errorString();
        return "";
    }
    // 读取文件内容（UTF-8编码）并转换为字符串
    QString jsonContent = QString::fromUtf8(file.readAll());
    file.close();
    return jsonContent;// 返回歌词JSON内容
}

// 设置歌曲列表
void MusicPlayerWidget::setSongList(const QList<SongInfo>& list)
{
    m_songList = list;
    if (!m_songList.isEmpty()) {
        switchSong(0); // 默认播放第一首
    }
}

// 解析歌词JSON（从JSON字符串中提取歌词）
void MusicPlayerWidget::parseLyricJson(const QString& jsonStr)
{
    m_currentLrcList.clear();
    if (jsonStr.isEmpty()) return;

    // 解析JSON文档
    QJsonParseError parseError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonStr.toUtf8(), &parseError);
    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "歌词JSON解析失败：" << parseError.errorString();
        return;
    }

    // 提取歌词文本（JSON结构：{"lrc":{"lyric":"歌词内容"}}）
    QJsonObject rootObj = jsonDoc.object();
    if (!rootObj.contains("lrc")) {
        qWarning() << "歌词JSON格式错误：缺少lrc字段";
        return;
    }
    QJsonObject lrcObj = rootObj["lrc"].toObject();
    QString lyricText = lrcObj["lyric"].toString();

    // 解析歌词中的时间标签（如 [00:32.84]）  timeRegex 定义了要匹配的模式
    QRegularExpression timeRegex(R"(\[(\d{2}):(\d{2})\.(\d{2})\])");
    //QRegularExpressionMatchIterator Qt 中的迭代器类，用于遍历正则表达式的所有匹配结果
    //QRegularExpression::globalMatch() 用于在整个字符串中查找所有匹配项
    QRegularExpressionMatchIterator iterator = timeRegex.globalMatch(lyricText);
    //作用是记录上一个时间标签在歌词文本中的结束位置，用于在解析歌词时准确提取两个时间标签之间的歌词内容。
    int lastPos = 0;//lastPos = 0 表示从歌词文本的起始位置（0 索引） 开始解析 ，记录上一个时间标签的结束位置
    
    //iterator.hasNext() 是 Qt 中正则表达式匹配迭代器的核心方法，用于检查是否还有下一个匹配结果。
    while (iterator.hasNext()) {
        QRegularExpressionMatch match = iterator.next();//用于获取下一个匹配结果
        // 转换时间为毫秒
        int minute = match.captured(1).toInt();
        int second = match.captured(2).toInt();
        int msec = match.captured(3).toInt() * 10; // 00->0ms，84->840ms
        //totalMs 是将歌词中的时间标签（如 [01:23.45]）转换后的总毫秒数
        qint64 totalMs = minute * 60000 + second * 1000 + msec;

        // 提取歌词内容  match.capturedStart() 返回当前匹配的时间标签（如 [00:32.84]）在歌词文本中的起始位置
        int currentPos = match.capturedStart();
        //trimmed() 去除字符串前后的空白字符（如换行符、空格）。
        //yricText.mid(pos, length) 从 pos 位置开始截取长度为 length 的子字符串
        //用当前匹配的起始位置减去上一个匹配的结束位置，得到的差值就是两个标签之间的歌词文本长度
        /*
        假设歌词文本为：

        plaintext
        [00:00.00]Hello[00:10.00]World[00:20.00]!

        解析步骤：

        第一个标签 [00:00.00]：
        lastPos = 0（初始值）。
        currentPos = 0（标签起始位置）。
        lyricContent = mid(0, 0-0) → 空字符串（跳过）。
        lastPos = 10（标签结束位置）。
        第二个标签 [00:10.00]：
        currentPos = 16（实际位置，假设 Hello 占 6 个字符）。
        lyricContent = mid(10, 16-10) → "Hello"（长度为 6）。
        lastPos = 26（[00:10.00] 的结束位置）。
        第三个标签 [00:20.00]：
        currentPos = 32（假设 World 占 5 个字符）。
        lyricContent = mid(26, 32-26) → "World"（长度为 5）。
        lastPos = 42。
        最后一段歌词：
        currentPos = 48（假设 ! 占 1 个字符）。
        lyricContent = mid(42, 48-42) → "!"（长度为 1）。
             
         */
        QString lyricContent = lyricText.mid(lastPos, currentPos - lastPos).trimmed();
        if (!lyricContent.isEmpty()) {
            m_currentLrcList.append({totalMs, lyricContent});
        }
        //match.capturedEnd() 返回当前匹配的时间标签在歌词文本中的结束位置
        lastPos = match.capturedEnd();
    }
}

// 根据播放进度更新当前歌词
void MusicPlayerWidget::updateCurrentLyric(qint64 position)
{
    // 遍历所有歌词行
    for (int i = 0; i < m_currentLrcList.size(); ++i) {
        const LrcLine& currentLine = m_currentLrcList[i];
        bool isLastLine = (i == m_currentLrcList.size() - 1);
        
        // 判断当前播放位置是否在当前歌词行的时间范围内
        /*
         * 1. 条件判断：position >= currentLine.timeMs
         * position：当前音乐的播放进度（单位：毫秒），由播放器实时提供。
            currentLine.timeMs：当前遍历的歌词行对应的时间戳（即前面计算的 totalMs，单位：毫秒）。
            含义：只有当音乐播放进度超过或等于某句歌词的时间戳时，这句歌词才有可能需要显示（还需满足下一个条件）。
            
            2. 条件判断：(isLastLine || position < m_currentLrcList[i+1].timeMs)
            isLastLine：标记当前歌词行是否是最后一句（i == m_currentLrcList.size() - 1）。
            m_currentLrcList[i+1].timeMs：下一句歌词的时间戳（单位：毫秒）。
         */
        if (position >= currentLine.timeMs && (isLastLine || position < m_currentLrcList[i+1].timeMs)) {
            m_lyricLabel->setText(currentLine.content);// 更新歌词显示
            break;
        }
    }
}

// 切换到指定歌曲
void MusicPlayerWidget::switchSong(int index)
{
    if (index < 0 || index >= m_songList.size()) return;
    m_currentIndex = index;

    // 获取当前歌曲信息
    const SongInfo& currentSong = m_songList[index];

    // 更新UI显示
    m_songNameLabel->setText(currentSong.name);
    m_artistLabel->setText(currentSong.artist);

    // 加载并解析歌词（从JSON文件读取）
    QString lyricJson = readLyricFromFile(currentSong.lyricPath);
    parseLyricJson(lyricJson);
    if (m_currentLrcList.isEmpty()) {
        m_lyricLabel->setText("暂无歌词");
    }

    // 加载并播放音频
    m_player->setMedia(QUrl::fromLocalFile(currentSong.filePath));
    m_playBtn->setPixmap(QPixmap(":/img/play.png"));
    
    // 重置GIF状态为暂停
    if (m_movie) m_movie->setPaused(true);
}

// 鼠标点击事件（处理按钮点击）
void MusicPlayerWidget::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        if (m_prevBtn->geometry().contains(event->pos())) {
            onPrevSong();
        } else if (m_playBtn->geometry().contains(event->pos())) {
            onPlayPause();
        } else if (m_nextBtn->geometry().contains(event->pos())) {
            onNextSong();
        }
    }
    QWidget::mousePressEvent(event);
}

// 上一首
void MusicPlayerWidget::onPrevSong()
{
    if (m_songList.isEmpty()) return;
    // 计算上一首歌曲的索引(循环处理)
    int prevIndex = (m_currentIndex - 1 + m_songList.size()) % m_songList.size();
    switchSong(prevIndex);// 切换到上一首歌曲
}

// 播放/暂停
void MusicPlayerWidget::onPlayPause()
{
    if (m_player->state() == QMediaPlayer::PlayingState) {
        m_player->pause();
        m_playBtn->setPixmap(QPixmap(":/img/play.png"));
        if (m_movie) m_movie->setPaused(true); // 暂停GIF
    } else {
        m_player->play();
         m_playBtn->setPixmap(QPixmap(":/img/pause.png"));
        if (m_movie) m_movie->setPaused(false); // 播放GIF
    }
}

// 下一首
void MusicPlayerWidget::onNextSong()
{
    if (m_songList.isEmpty()) return;
    // 计算下一首歌曲的索引(循环处理)
    int nextIndex = (m_currentIndex + 1) % m_songList.size();
    switchSong(nextIndex);
}



// 播放进度变化（更新进度条和歌词）
void MusicPlayerWidget::onPositionChanged(qint64 position)
{
    m_progressSlider->setValue(position);
    updateCurrentLyric(position); // 更新歌词
}

// 音频时长变化（设置进度条范围）
void MusicPlayerWidget::onDurationChanged(qint64 duration)
{
    m_progressSlider->setRange(0, duration);
}

// 进度条拖拽（调整播放进度）
void MusicPlayerWidget::onProgressDragged(int position)
{
    m_player->setPosition(position);
}
